#include "HttpRequest.hpp"


HttpRequest::HttpRequest() {
    reset();
}

void HttpRequest::reset() {
    currentState_ = ParseState::ParseLine;
    method_ = url_ = version_ = body_ = std::string();
    reqHeaders_.clear();
}

void HttpRequest::addHeader(const std::string& key, const std::string& value) {
    if (key.empty() || value.empty()) {
        return ;
    }
    reqHeaders_.insert({key, value});
}

std::string HttpRequest::getHeader(const std::string& key) {
    if (reqHeaders_.find(key) == reqHeaders_.end()) {
        return std::string();
    }
    return reqHeaders_[key];
}


bool HttpRequest::parseLine(Buffer* buffer) {
    assert(currentState_ == ParseState::ParseLine);
    
    std::string firstLine = buffer->getSplit<std::string>("\r\n", 2);
    int start=0;
    int end = firstLine.find(' ');
    if (end == std::string::npos) {
        currentState_ = ParseState::ParseErr;
        return false;
    }
    method_ = firstLine.substr(start, end-start);
    if (method_ != "GET" && method_ != "POST") {
        currentState_ = ParseState::ParseErr;
        return false;
    }



    start = end+1;
    if (start >= firstLine.size()) {
        currentState_ = ParseState::ParseErr;
        return false;
    }
    end = firstLine.find(' ', start);
    if (end == std::string::npos) {
        currentState_ = ParseState::ParseErr;
        return false;
    }
    url_ = firstLine.substr(start, end-start);

    // 解析url的参数
    int index = url_.find('?');
    if (index != std::string::npos) {
        urlParam_ = UrlDecode(url_.substr(index+1, url_.size()-index-1));
        url_ = url_.substr(0, index);
        std::cout << url_ << ' ' << urlParam_ <<std::endl;
    }

    start = end+1;
    if (start >= firstLine.size()) {
        currentState_ = ParseState::ParseErr;
        return false;
    }
    version_ = firstLine.substr(start, firstLine.size() - start);

    currentState_ = ParseState::ParseHeaders;
    return true;
}


bool HttpRequest::parseHeader(Buffer* buffer) {
    assert(currentState_ == ParseState::ParseHeaders);
    std::string line = buffer->getSplit<std::string>("\r\n", 2);
    if (line.size() == 0) {
        currentState_ = ParseState::ParseBody;
        return true;
    }
    std::string theLine(line.begin(), line.end());
    int idx = theLine.find(':');
    if (idx == std::string::npos) {
        currentState_ = ParseState::ParseErr;
        return false;
    }
    std::string key = theLine.substr(0, idx);
    int valueStart = idx+1;
    while (theLine[valueStart] == ' ') valueStart++;
    std::string value = theLine.substr(valueStart, theLine.size() - valueStart);
    addHeader(key, value);
    return true;
}


bool HttpRequest::parseBody(Buffer* buff) {
    if (reqHeaders_.find("Content-Length") == reqHeaders_.end() || reqHeaders_["Content-Length"] == "0") {
        currentState_ = ParseState::ParseDone;
        return true;
    }
    int contentLen = atoi(reqHeaders_["Content-Length"].c_str());
    if (contentLen <= 0) {
        currentState_ = ParseState::ParseErr;
        return false;
    }
    body_ = buff->getData<std::string>(contentLen);
    return true;
}

bool HttpRequest::peekBuffer(Buffer* buffer) {
    // 先找\r\n\r\n，找不到说明请求头不完整，直接返回。
    const char* headerEndPtr = buffer->findCRLF("\r\n\r\n", 4);
    if (headerEndPtr == NULL) return false;

    // 在请求头中找content-length，不区分大小写，获取body的长度，
    const char* contentLenPtr = buffer->findCRLF("Content-Length: ", 16);

    // 找不到说明没有body，说明请求完整
    if (contentLenPtr == NULL) return true;
    
    // 找到了就看buffer剩余的内容是否大于等于content-length，是则请求完整，否则不完整。
    contentLenPtr += 16;
    int len = 0;
    while (*contentLenPtr < '9' && *contentLenPtr > '0') {
        len*=10;
        len += (*contentLenPtr-'0');
        contentLenPtr ++;
    }

    const char* bufferEnd = buffer->getWritePos();
    if (bufferEnd - (headerEndPtr + 4) >= len) return true;
    return false;

}

void HttpRequest::parseOneRequset(Buffer* buffer) {
    reset();
    while (currentState_ == ParseState::ParseLine) {
        parseLine(buffer);
    }
    if (currentState_ == ParseState::ParseErr) {
        return ;
    }
    while (currentState_ == ParseState::ParseHeaders) {
        parseHeader(buffer);
    }
    if (currentState_ == ParseState::ParseErr) {
        return ;
    }
    parseBody(buffer);
    if (currentState_ == ParseState::ParseErr) {
        return ;
    }
}




const std::string HttpRequest::getInfo() {
    std::string result = "";
    result += (method_ + " " + url_+ " " + version_ + "\r\n");
    for (auto it = reqHeaders_.begin(); it != reqHeaders_.end(); ++it) {
        result += (it->first + ":" + it->second + "\r\n");
    }
    result += "\r\n";
    result += body_ + "\r\n";
    return result;
}